let listeners=new Map()
/**
 * 1. 事件管理器，实体对象通过继承该类，从而具有事件的分发和监听的能力。
 * 2. 非实例类，不可直接实例化。
 * 3. 事件队列遵循先进后出，即先注册后触发，以实现后面注册的事件能对事件有一定的干预能力，比如阻止事件流。
 * @class
 * @memberof w.event
 */
class Evented{
    constructor(){
    }
    /**
     * 监听系统分发的type类型的事件,先注册，先响应。
     * @method
     * @param type {String} 事件类型
     * @param callback {Function} 事件监听到后的响应函数
     */
    on(type, callback) {
        let has = listeners.get(type);
        if (!has) {
            listeners.set(type, []);
        }
        listeners.get(type).push({ scope: this, callback: callback,once:false});
    }
    /**
     * 监听系统分发的type类型的事件。不同于on，一旦响应一次会销毁该事件，并移除监听.
     * @method
     * @param type {String} 事件类型
     * @param callback {Function} 事件监听到后的响应函数
     */
    once(type, callback) {
        let has = listeners.get(type);
        if (!has) {
            listeners.set(type, []);
        }
        listeners.get(type).push({ scope: this, callback: callback,once:true});
    }
    /**
     * 取消监听系统分发的type类型的事件。
     * @method
     * @param type {String} 事件类型
     * @param callback {Function} 事件监听到后的响应函数
     */
    off(type, callback) {
        if (!callback) {
            listeners.delete(type);
        } else {
            let len = 0;
            //从handler中删除确定的callback
            const listener = listeners.get(type);
            if (listener) {
                len = listener.length;
                for (let i = len - 1; i >= 0; i--) {
                    if (listener[i].callback == callback) {
                        listener.splice(i, 1);
                    }
                }
            }
        }
    }

    /**
     * 派发事件。
     * @method
     * @param {w.event.Event} event  事件
     */
    publish(event) {
        let listener = listeners.get(event.type);
        if (listener) {
            let len = listener.length;
            for (let i = len - 1; i >= 0; i--) {
                const handler = listener[i];
                if(!handler){
                    continue;
                }
                handler.callback.call(handler.scope, event);
                event.currentTarget = handler.scope;
                if (handler.once) {
                    listener.splice(i, 1);
                }
                if (event.prevent) {
                    break;
                }
            }
            event=null;
        }
    }
    clearEvent(){
        listeners.clear();
    }
}
export {Evented}
